<template>
  <el-row>
    <el-col :span="15">
      <MainModule>
        <template #header>
          <div class="notify">
            <el-icon size="24">
              <QuestionFilled />
            </el-icon>
            <el-text type="danger">&nbsp;低等级角色无法修改高等级角色，数字越小等级越高</el-text>
            <el-button type="primary" @click="Create">新增角色</el-button>
          </div>
        </template>

        <MyTable v-bind="MyTableData" :serial="(table.param.Page - 1) * table.param.PageSize + 1">
          <template #Operation="{ row }">
            <el-button size="small" type="primary" @click="Edit(row)">编辑</el-button>
            <el-button size="small" type="danger" @click="Delete(row)">删除</el-button>
          </template>
          <template #EditAuth="{ row }">
            <el-button size="small" type="success" @click="EditAuth(row)">编辑</el-button>
          </template>
        </MyTable>
        <EditingDialog :fromParam="EditRoleDialogParams" :GetData="GetData"></EditingDialog>

        <template #footer>
          <MyPagination :total="table.total" v-model:currentPage="table.param.Page"
            v-model:pageSize="table.param.PageSize" @change="GetData"></MyPagination>
        </template>
      </MainModule>
    </el-col>
    <el-col :span="24 - 15">
      <MainModule>
        <div class="menu-permissions">
          <span>菜单{{ EditRolePowerParams.modal ? "--权限编辑" : "" }}</span>

          <template v-if="!!tree.data.length && EditRolePowerParams.modal">
            <el-dropdown trigger="click" @command="HandleCommand">
              <el-button icon="List" type="primary" plain>快捷选项</el-button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item icon="SuccessFilled" command="Check">勾选全部</el-dropdown-item>
                  <el-dropdown-item icon="CircleCloseFilled" command="Close">清空勾选</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>

            <div>
              当前编辑角色：
              <el-text type="danger" size="large">{{ EditRolePowerParams.params.Name }}</el-text>
            </div>
          </template>
        </div>

        <el-tree v-loading="tree.loading" ref="authTreeRef" :data="tree.data" :props="tree.props"
          :node-key="tree.props.id" default-expand-all :show-checkbox="EditRolePowerParams.modal">
          <template #empty>
            <div style="height: 64px;line-height: 64px;">
              暂无菜单数据
            </div>
          </template>
        </el-tree>

        <template #footer v-if="!!tree.data.length">
          <template v-if="EditRolePowerParams.modal">
            <el-button @click="CloseReset">取消</el-button>
            <el-button type="primary" @click="UpdateRoleMenu" :loading="editRoleLoading">提交</el-button>
          </template>
          <template v-else>
            <el-button type="primary" @click="NotSelectedRole">选择角色后编辑</el-button>
          </template>
        </template>
      </MainModule>
    </el-col>
  </el-row>
</template>

<script lang="ts" setup>
import { MainModule, MyPagination, MyTable, type MyTableType } from "@/components"
import { ref, reactive, onMounted, onUnmounted } from 'vue';
import { type ElTree } from 'element-plus';
import { RoleApiUrl, RoleApi } from '@/api/permession/role'
import { MenuApiUrl, MenuApi } from "@/api/permession/menu";
import { PaginationParams } from "@/library/common"
import config from '@/config';
import { nextTick } from 'vue';
import { PermessionRole } from "./Def"
import { columns } from "./ConfigData"
import EditingDialog from './EditingDialog.vue';
import { useMainLoading } from "@/hooks/useMainLoading"
import { AbortApi } from "@/library/utils/request";
import MessageUti from "@/library/utils/MessageUti"

const { openMainLoading, closeMainLoading } = useMainLoading()

const param: PermessionRole.ParamState = {
  ...PaginationParams
}

const defaultParams: PermessionRole.ParamsState = {
  Id: undefined,
  Enable: false,
  Sort: 0,
  Name: '',
  Desc: '',
  MenuList: undefined
}

const tree = reactive<PermessionRole.TreeState>({
  data: [],
  loading: false,
  props: {
    id: "Id",
    children: "Children",
    label: "Name",
    value: "ClassName"
  },
  allTreeNodeKeyS: [] // 全部树节点 node-key
})

const table = reactive<PermessionRole.TableState>({
  param: { ...param },
  total: 0
})

// 表格配置数据
const MyTableData = reactive<MyTableType>({
  loading: false,
  table: {
    data: []
  },
  columns
})

const GetMenus = async () => {
  tree.loading = true
  let param = {
    AppId: config.AppId,
  };

  await MenuApi.SelectMenus(param).then((res) => {
    tree.data = res.Data
    tree.loading = false
  })
}

const GetData = async () => {
  MyTableData.loading = true

  await RoleApi.SelectRoles({ ...table.param }).then((res) => {
    res.Data.Data.forEach((item: any) => {
      item.Operation = ''
      item.EditAuth = ''
    })

    MyTableData.table.data = res.Data.Data
    table.total = res.Data.Count
    MyTableData.loading = false
  })
}

const Delete = async (row: PermessionRole.ParamsState) => {
  const confirm = await MessageUti.confirm("删除角色", `是否删除角色 ${row.Name} ?`)
  if (!confirm) { return }

  RoleApi.DeleteRole({ Id: row.Id }).then((res) => {
    GetData();
    table.param = { ...param }
    MessageUti.showSuccess('删除成功');

    // 在此之前 如有在编辑菜单权限 则关闭菜单编辑权限
    EditRolePowerParams.modal && CloseReset()
  });
};

// 编辑角色 dialog 使用数据
const EditRoleDialogParams = reactive<PermessionRole.EditingDialog>({
  modal: false,
  params: { ...defaultParams }
})

const Create = () => {
  EditRoleDialogParams.modal = true
}

const Edit = (row: PermessionRole.ParamsState) => {
  // 在此之前 如有在编辑菜单权限 则关闭菜单权限编辑
  EditRolePowerParams.modal && CloseReset()

  let { Id, Enable, MenuList, Sort, Name, Desc } = row

  EditRoleDialogParams.modal = true
  EditRoleDialogParams.params = { Id, Enable, MenuList, Sort, Name, Desc }
}

const authTreeRef = ref<InstanceType<typeof ElTree>>()

/**
 * @description 获取所有树节点的 node-key 唯一标识
 * @param data 树节点数据
 */
const GetTreeNodeKeys = <T extends Array<any>>(data: T) => {
  // 获取树节点 key 和 children 的字段名
  let { id, children } = tree.props

  // 进行查找
  function searchKey(data: T) {
    data.forEach(val => {
      // 存储树节点 node-key
      tree.allTreeNodeKeyS.push(val[id])

      // 有叶子节点 继续搜寻
      val[children]?.length && searchKey(val[children])
    })
  }

  searchKey(data)
}

// 编辑角色权限使用数据
const EditRolePowerParams = reactive<PermessionRole.EditingRole>({
  modal: false,
  params: { ...defaultParams }
})

/**
 * @description 选择对应角色的 编辑权限
 * @param row 当前角色数据
 */
const EditAuth = (row: PermessionRole.ParamsState) => {
  if (!!!tree.data.length) {
    MessageUti.showInfo("暂无可编辑的菜单权限")
    return
  }

  EditRolePowerParams.modal = true
  let MenuList = [...row.MenuList || []]
  EditRolePowerParams.params = { ...row, MenuList }

  // 清空勾选
  authTreeRef.value?.setCheckedKeys([], true)

  // 勾选拥有权限
  MenuList.forEach(menu => {
    authTreeRef.value?.setChecked(menu, true, false)
  })
}

// 未选择角色
const NotSelectedRole = () => {
  MessageUti.confirm("尚未选择角色", "请选择任意一个角色后在进行操作!", undefined, {
    showCancelButton: false,
    confirmButtonText: "知道了"
  })
}

// 快捷选项
const HandleCommand = (command: "Check" | "Close") => {
  let arr = (command === "Check") ? tree.allTreeNodeKeyS : []
  authTreeRef.value?.setCheckedKeys(arr)
}

const editRoleLoading = ref(false)
const UpdateRoleMenu = async () => {
  editRoleLoading.value = true
  let CheckedKeys = authTreeRef.value?.getCheckedKeys() || [] // 当前勾选节点(不包含半勾选节点)
  let halfCheckedKeys = authTreeRef.value?.getHalfCheckedKeys() || []  // 半勾选节点

  let AllCheckedKeys = [...CheckedKeys, ...halfCheckedKeys] // 全部勾选节点

  let params = {
    Id: EditRolePowerParams.params.Id,
    MenuList: AllCheckedKeys
  }

  RoleApi.UpdateRoleMenuList({ ...params }).then(
    () => {
      MessageUti.showSuccess('提交成功')
      CloseReset()
      GetMenus()
      GetData()
    },
    () => { }
  )
    .finally(() => {
      editRoleLoading.value = false
    })
}

const CloseReset = () => {
  EditRolePowerParams.modal = false
  nextTick(() => {
    EditRolePowerParams.params = { ...defaultParams }
  })
}

onMounted(async () => {
  openMainLoading()
  await GetData()
  await GetMenus()
  GetTreeNodeKeys(tree.data || [])
  closeMainLoading()
})

onUnmounted(() => {
  AbortApi([RoleApiUrl.SelectRoles, MenuApiUrl.SelectMenus])
})

</script>

<style lang="scss" scoped>
.notify {
  height: 32px;
  display: flex;
  align-items: center;

  &>:last-child {
    margin-left: auto;
  }
}

.menu-permissions {
  padding-bottom: 10px;

  span {
    font-weight: bold;
    line-height: 32px;
    margin-right: 10px;
    font-size: 20px;
  }
}
</style>